#ifndef COMMON_H
#define COMMON_H
#include <cmath> // Ensure the cmath header is included
#include <qnumeric.h>

class Point {
public:

	constexpr inline Point& operator+=(const Point& p);
	constexpr inline Point& operator-=(const Point& p);

	Point() {
		tx = 0;
		ty = 0;
	}
	Point(float x, float y) {
		tx = x;
		ty = y;
	}

	~Point() {
	}

	Point(Point& p) {
		tx = p.tx;
		ty = p.ty;
	}

	void setX(float x) {
		tx = x;
	}

	void setY(float y) {
		ty = y;
	}

	float x() {
		return tx;
	}

	float y() {
		return ty;
	}

	float cross(Point p) {
		return tx * p.y() - ty * p.x();
	}

	float dot(Point p) {
		return tx * p.tx + ty * p.ty;
	}

	void from(const Point& p) {
		this->tx = p.tx;
		this->ty = p.ty;
	}
	Point add(Point p) {
		return Point(this->tx + p.x(), this->ty + p.y());
	}
protected:
	float tx=0;
	float ty=0;
};

constexpr inline Point& Point::operator+=(const Point& p)
{
	tx += p.tx;
	ty += p.ty;
	return *this;
}

constexpr inline Point& Point::operator-=(const Point& p)
{
	tx -= p.tx;
	ty -= p.ty;
	return *this;
}

class Vector {
public:
	Vector() :data{ 0,0 } {}

	~Vector() {
	}

	Vector(float x, float y) {
		data[0] = x;
		data[1] = y;
	}
	Point toPoint() {
		return Point(data[0], data[1]);
	}
	Vector normalized();
	void normalize();
	float length();
	void from(Vector p) {
		data[0] = p.x();
		data[1] = p.y();
	}

	float x() {
		return data[0];
	}

	float y() {
		return data[1];
	}
private:
	float data[2];
};

inline float Vector::length()
{
	using std::hypot;
	return hypot(data[0], data[1]);
}


inline Vector Vector::normalized()
{
	const float len = length();
	return qFuzzyIsNull(len - 1.0f) ? *this : qFuzzyIsNull(len) ? Vector()
		: Vector(data[0] / len, data[1] / len);
}

inline void Vector::normalize()
{
	const float len = length();
	if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len))
		return;

	data[0] /= len;
	data[1] /= len;
}

#endif
